package com.swt.gap.service.impl;

import com.swt.gap.common.constant.GraphDbConstant;
import com.swt.gap.common.NodeTypeEnum;
import com.swt.gap.config.ServerConfig;
import com.swt.gap.dao.*;
import com.swt.gap.model.entity.Model;
import com.swt.gap.model.entity.OntologyNode;
import com.swt.gap.model.entity.SysIcon;
import com.swt.gap.model.entity.TaskLabels;
import com.swt.gap.model.vo.CountPropertyVO;
import com.swt.gap.model.vo.LabelProperty;
import com.swt.gap.model.vo.Model2VO;
import com.swt.gap.model.vo.ModelByClassVO;
import com.swt.gap.model.vo.element.EventElementVO;
import com.swt.gap.model.vo.graph.GraphModel;
import com.swt.gap.model.vo.ontology.ListLevelNodeVO;
import com.swt.gap.model.vo.ontology.OntologyNodeVO;
import com.swt.gap.service.Model2Service;
import com.swt.gap.service.OntologyNodeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 请填写说明
 *
 * @author sx
 * @date 2020/6/4 16:49
 */
@Service
public class OntologyNodeServiceImpl implements OntologyNodeService {



    private final TaskLabelsDao taskLabelsDao;
    private final OntologyNodePropertyDao ontologyNodePropertyDao;
    private final OntologyNodeDao ontologyNodeDao;
    private final ServerConfig serverConfig;
    private final SysIconMapper sysIconMapper;
    private final OntologyRelationshipMapper ontologyRelationshipMapper;
    private final Model2Service model2Service;

    public OntologyNodeServiceImpl(TaskLabelsDao taskLabelsDao, OntologyNodePropertyDao ontologyNodePropertyDao,
                                   OntologyNodeDao ontologyNodeDao,
                                   ServerConfig serverConfig,
                                   SysIconMapper sysIconMapper,
                                   OntologyRelationshipMapper ontologyRelationshipMapper,
                                   Model2Service model2Service){
        this.taskLabelsDao = taskLabelsDao;
        this.ontologyNodePropertyDao = ontologyNodePropertyDao;
        this.ontologyNodeDao = ontologyNodeDao;
        this.serverConfig = serverConfig;
        this.sysIconMapper = sysIconMapper;
        this.ontologyRelationshipMapper = ontologyRelationshipMapper;
        this.model2Service = model2Service;
    }

    @Override
    public List<ListLevelNodeVO> listLevelNode() {
        List<ListLevelNodeVO> retValue = new ArrayList<>();
        List<OntologyNode> allNodes = ontologyNodeDao.selectAll();
        for (NodeTypeEnum nodeTypeEnum : NodeTypeEnum.values()) {
            if(nodeTypeEnum != NodeTypeEnum.EXTERNAL) {
                List<OntologyNodeVO> ontologyEntityList = new ArrayList<>();
                Iterator<OntologyNode> iterator = allNodes.iterator();
                while (iterator.hasNext()) {
                    OntologyNode ontologyEntity = iterator.next();
                    String[] labels = ontologyEntity.getLabels().split(",");
                    if (nodeTypeEnum.getName().equals(labels[0])) {
                        OntologyNodeVO oe = new OntologyNodeVO();
                        BeanUtils.copyProperties(ontologyEntity, oe);
                        oe.setLabels(labels[1]);
                        SysIcon sysIcon = sysIconMapper.selectByPrimaryKey(ontologyEntity.getIconId());
                        oe.setViewUrl(serverConfig.parseViewUrl(sysIcon.getIconFile(), 3));
                        oe.setOntologyNodePropertyList(ontologyNodePropertyDao.selectByEntityId(ontologyEntity.getNodeId()));
                        ontologyEntityList.add(oe);
                        iterator.remove();
                    }
                }
                ListLevelNodeVO listLevelNodeVO = new ListLevelNodeVO(nodeTypeEnum.getName(), ontologyEntityList);
                retValue.add(listLevelNodeVO);
            }
        }
        return retValue;
    }

    @Override
    public List<CountPropertyVO> listNodeCountProperty(Integer taskId) {
        List<CountPropertyVO> retValue = new ArrayList<>();
        List<TaskLabels> taskLabels = taskLabelsDao.listTaskLabelsByTaskId(taskId);
        for (NodeTypeEnum nodeTypeEnum : NodeTypeEnum.values()) {
            CountPropertyVO countProperty = new CountPropertyVO();
            String firstLabel = nodeTypeEnum.getName();
            countProperty.setFirstLabel(firstLabel);
            List<CountPropertyVO.LabelCountProperties> secondLabelCountProperties = new ArrayList<>();

            taskLabels.forEach(taskLabel -> {
                String labels = taskLabel.getLabels();
                String[] labelArr = labels.split(",");
                if (firstLabel.equals(labelArr[0])) {
                    String secondLabel = labelArr[1];
                    CountPropertyVO.LabelCountProperties second = new CountPropertyVO.LabelCountProperties();
                    second.setSecondLabel(secondLabel);
                    second.setPropertyKeys(ontologyNodePropertyDao.listCountPropertyKeyByLabels(labels));
                    secondLabelCountProperties.add(second);
                }
            });
            countProperty.setSecondLabelCountProperties(secondLabelCountProperties);
            retValue.add(countProperty);
        }
        return retValue;
    }

    @Override
    public List<LabelProperty> listEventNodeProperty(Integer taskId) {
        List<LabelProperty> retValue = new ArrayList<>();
        retValue.add(new LabelProperty(GraphDbConstant.EVENT_TYPE, 1));
        List<TaskLabels> taskLabels = taskLabelsDao.listTaskLabelsByTaskId(taskId);
        taskLabels.forEach(taskLabel -> {
            String labels = taskLabel.getLabels();
            if(labels.startsWith(NodeTypeEnum.EVENT.getName() + ",")) {
                List<String> keys = ontologyNodePropertyDao.listPropertyKeyByLabels(taskLabel.getLabels());
                keys.forEach(key -> {
                    retValue.add(new LabelProperty(key, 2));
                });
            }
        });
        return retValue;
    }

    @Override
    public List<OntologyNodeVO> listAllOntologyNodeAndProperty() {
        List<OntologyNodeVO> ontologyEntityList = new ArrayList<>();
        List<OntologyNode> ontologyEntities = ontologyNodeDao.selectAll();
        ontologyEntities.forEach(ontologyEntity -> {
            OntologyNodeVO oe = new OntologyNodeVO();
            BeanUtils.copyProperties(ontologyEntity, oe);
            oe.setOntologyNodePropertyList(ontologyNodePropertyDao.selectByEntityId(ontologyEntity.getNodeId()));
            ontologyEntityList.add(oe);
        });
        return ontologyEntityList;
    }

    @Override
    public List<EventElementVO> listEventElementsAndRelNodeById(Integer nodeId) {
        //事件节点的属性
        List<EventElementVO> propertyElements = ontologyNodePropertyDao.selectKeyByOntologyNodeId(nodeId);
        //事件节点的关联节点
        List<EventElementVO> nodeElements = ontologyRelationshipMapper.selectEntityByOntologyNodeId(nodeId);
        nodeElements.forEach(nodeElement -> {
            String element = nodeElement.getElement();
            nodeElement.setElement(StringUtils.substringAfterLast(element, ","));
            propertyElements.add(nodeElement);
        });
        return propertyElements;
    }

    @Override
    public List<EventElementVO> listEventElementsById(Integer nodeId) {
        //事件节点的属性
        return ontologyNodePropertyDao.selectKeyByOntologyNodeId(nodeId);
    }

    @Override
    public Set<OntologyNodeVO> listRecommendNodes(List<String> header) {
        Set<OntologyNodeVO> retValue = new HashSet<>();

        Integer matchModelId = 0;
        int sameHeaderCount = 0;
        List<ModelByClassVO> allModels = model2Service.listModel();
        for(ModelByClassVO classModel : allModels) {
            for (Model model : classModel.getModels()) {
                List<String> modelFields = new ArrayList<>(Arrays.asList(model.getMatchField().split(",")));
                modelFields.retainAll(header);
                if(modelFields.size() > sameHeaderCount) {
                    sameHeaderCount = modelFields.size();
                    matchModelId = model.getModelId();
                }
            }
        }
        if(!matchModelId.equals(0)) {
            List<GraphModel> graphModels = model2Service.getModelById(matchModelId).getGraphModels();
            graphModels.forEach(model -> {
                OntologyNodeVO retNode = new OntologyNodeVO();
//                int id = model.getStartNodeConfig().getOntologyNodeId();
//                OntologyNode ontologyNode = ontologyNodeDao.selectByPrimaryKey(id);

                List<String> labels = model.getStartNodeConfig().getLabels();
                OntologyNode ontologyNode = ontologyNodeDao.selectByLabels(String.join(",", labels)).get(0);

                SysIcon sysIcon = sysIconMapper.selectByPrimaryKey(ontologyNode.getIconId());
                retNode.setViewUrl(serverConfig.parseViewUrl(sysIcon.getIconFile(), 3));
                retNode.setNodeId(ontologyNode.getNodeId());
                retNode.setLabels(ontologyNode.getLabels());
                retNode.setOntologyNodePropertyList(ontologyNodePropertyDao.selectByEntityId(ontologyNode.getNodeId()));
                retValue.add(retNode);



                retNode = new OntologyNodeVO();
//                id = model.getEndNodeConfig().getOntologyNodeId();
//                ontologyNode = ontologyNodeDao.selectByPrimaryKey(id);
                labels = model.getEndNodeConfig().getLabels();
                ontologyNode = ontologyNodeDao.selectByLabels(String.join(",", labels)).get(0);

                sysIcon = sysIconMapper.selectByPrimaryKey(ontologyNode.getIconId());
                retNode.setViewUrl(serverConfig.parseViewUrl(sysIcon.getIconFile(), 3));
                retNode.setNodeId(ontologyNode.getNodeId());
                retNode.setLabels(ontologyNode.getLabels());
                retNode.setOntologyNodePropertyList(ontologyNodePropertyDao.selectByEntityId(ontologyNode.getNodeId()));
                retValue.add(retNode);

            });
        }
        return retValue;
    }

    @Override
    public List<OntologyNode> listFirstLevelNode() {
        List<OntologyNode> nodes = ontologyNodeDao.selectFirstLevel();
        nodes.forEach(node -> {
            String label = node.getLabels();
            if(label.contains(",")) {
                label = label.substring(label.lastIndexOf(",") + 1);
                node.setLabels(label);
            }
        });
        return nodes;
    }

    @Override
    public List<OntologyNode> listChildrenNodesById(Integer nodeId) {
        List<OntologyNode> nodes = ontologyNodeDao.selectChildrenNodes(nodeId);
        nodes.forEach(node -> {
            String label = node.getLabels();
            if(label.contains(",")) {
                label = label.substring(label.lastIndexOf(",") + 1);
                node.setLabels(label);
            }
        });
        return nodes;
    }
}
